﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Collections.TreeCollections;
using FeatureModelCore.FMTypes;
using System.Xml.Linq;
using Collections;
using FeatureModelCore.FMInterface;

namespace FeatureModelCore
{
    public class FeatureNodeProperty : TreeLeaf, IFeatureModelObject
    {
        #region Property
        /// <summary>
        /// Type
        /// </summary>
        public FMPropertyType Type { get { return _type; } }
        public string PropertyName { get { return _propertyName; } }
        public string PropertyValue { get { return _propertyValue; } set { _propertyValue = value; } }
        #endregion

        #region Symbol
        public static readonly string _XML_SYMBOL_NAME = "PropertyName";
        public static readonly string _XML_SYMBOL_VALUE = "PropertyValue";
        public static readonly string _XML_SYMBOL_TYPE = "PropertyType";
        #endregion

        #region Fields
        /// <summary>
        /// Type
        /// </summary>
        private FMPropertyType _type;
        private string _propertyName;
        private string _propertyValue;

        private bool _existError;
        private FMSet<ErrorType> _errorMessage;
        private bool _existWarning;
        private FMSet<WarningType> _warningMessage;
        #endregion

        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <param name="propertyType"></param>
        internal FeatureNodeProperty(TreeNodeIdentify id, string propertyName, FMPropertyType propertyType)
            : base(id)
        {
            // valid property Name
            _type = propertyType;
            _propertyName = propertyName;
            _propertyValue = string.Empty;

            _existWarning = false;
            _existError = false;
            _errorMessage = new FMSet<ErrorType>();
            _warningMessage = new FMSet<WarningType>();
        }

        /// <summary>
        /// Construct Property
        /// </summary>
        /// <param name="id"></param>
        /// <param name="args">
        /// args[0]: property Name
        /// args[1]: </param>
        /// <returns></returns>
        public static FeatureNodeProperty ConstructProperty(
            TreeNodeIdentify id, object[] args)
        {
            string propertyName = string.Empty;
            FMPropertyType type = default(FMPropertyType);
            if (args != null)
            {
                propertyName = (string)args[0]; 
                type = (FMPropertyType)args[1];
            }
            return new FeatureNodeProperty(id, propertyName, type);
        }

        #region Xml Parser
        /// <summary>
        /// To Xelement
        /// </summary>
        /// <returns></returns>
        public override XElement ToXElem()
        {
            XElement xelem =  base.ToXElem();
            xelem.Add(new XAttribute(_XML_SYMBOL_NAME, _propertyName));
            xelem.Add(new XAttribute(_XML_SYMBOL_VALUE, _propertyValue));
            xelem.Add(new XAttribute(_XML_SYMBOL_TYPE, _type));

            return xelem;
        }
        /// <summary>
        /// Xml Parse
        /// </summary>
        /// <param name="xelem"></param>
        /// <returns></returns>
        internal static void xmlParser(XElement xelem, TreeObject obj)
        {
            FeatureNodeProperty newProperty = obj as FeatureNodeProperty;
            if (newProperty == null)
            {
                throw new Exception("Type Error!");
            }

            string propertyName = xelem.Attribute(_XML_SYMBOL_NAME).Value;
            string propertyValue = xelem.Attribute(_XML_SYMBOL_VALUE).Value;
            string typeStr = xelem.Attribute(_XML_SYMBOL_TYPE).Value;

            FMPropertyType type = (FMPropertyType)Enum.Parse(typeof(FMPropertyType), typeStr);

            newProperty._propertyName = propertyName;
            newProperty._propertyValue = propertyValue;
            newProperty._type = type;
        }
        #endregion


        public override string ToString()
        {
            return string.Format("Name:{0}; Value:{1}"
                , this._propertyName
                , this._propertyValue);
        }

        #region Error & Message
        /// <summary>
        /// Exist Error
        /// </summary>
        public bool ExistError { get { return _existError; } }
        /// <summary>
        /// Error Message
        /// </summary>
        public ErrorType[] ErrorMessages { get { return _errorMessage.ToArray<ErrorType>(); } }
        /// <summary>
        /// Clear Error all Message
        /// </summary>
        public void ClearErrorMessages()
        {
            this._errorMessage.Clear();
            this._existError = false;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="msg"></param>
        public void AddErrorMessage(ErrorType msg)
        {
            this._errorMessage.Add(msg);
            this._existError = true;
        }
        /// <summary>
        /// Exist Warning
        /// </summary>
        public bool ExistWarning { get { return _existWarning; } }
        /// <summary>
        /// Clear All Warning Messages
        /// </summary>
        public void ClearWarningMessages()
        {
            this._warningMessage.Clear();
            this._existWarning = false;
        }
        /// <summary>
        /// Add warning msg
        /// </summary>
        /// <param name="msg"></param>
        public void AddWarningMessage(WarningType msg)
        {
            this._warningMessage.Add(msg);
            this._existWarning = true;
        }
        /// <summary>
        /// Warning Messages
        /// </summary>
        public WarningType[] WarningMessages { get { return _warningMessage.ToArray<WarningType>(); } }
        #endregion

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            FeatureNodeProperty property = new FeatureNodeProperty(this.ID
                , this._propertyName, this._type);
            property._propertyValue = this._propertyValue;
            return property;
        }
    }
}
